//
//  WKDictionary.m
//  WKDictionary
//
//  Created by 周维康 on 16/6/20.
//  Copyright © 2016年 周维康. All rights reserved.
//

#import "WKDictionary.h"
#import <objc/runtime.h>

@interface WKDictionary()

@property (nonatomic, strong) NSMutableDictionary *backingStore;

@end

@implementation WKDictionary

@dynamic string, number, opaqueObject;

- (instancetype)init
{
    if (self = [super init])
    {
        _backingStore = [NSMutableDictionary new];
    }
    return self;
}

+ (BOOL)resolveInstanceMethod:(SEL)sel
{
    NSString *selectorString = NSStringFromSelector(sel);
    if ([selectorString hasPrefix:@"set"]) {
        class_addMethod(self, sel, (IMP)autoDictionarySetter, "v@:@");
    } else {
        class_addMethod(self, sel, (IMP)autoDictionaryGetter, "@@:");
    }
    return YES;
}

id autoDictionaryGetter(id self, SEL _cmd) {
    //Get the backing store from the object
    WKDictionary *typedSelf = (WKDictionary *)self;
    NSMutableDictionary *backingStore = typedSelf.backingStore;
    
    //The key is simply the selector name
    NSString *key = NSStringFromSelector(_cmd);
    
    //Return the value
    return [backingStore objectForKey:key];
}

void autoDictionarySetter(id self, SEL _cmd, id value) {
    //Get the backing store from the object
    WKDictionary *typedSelf = (WKDictionary *)self;
    NSMutableDictionary *backingStore = typedSelf.backingStore;
    
    /**
     *  The selector will be for example, "setOpaqueobject:"/
     *  We need to remove the "set", ":" and lowercase the first
     *  letter of the remainder
     */
    
    NSString *selectorString = NSStringFromSelector(_cmd);
    NSMutableString *key = [selectorString mutableCopy];
    
    [key deleteCharactersInRange:NSMakeRange(key.length - 1, 1)];
    
    [key deleteCharactersInRange:NSMakeRange(0, 3)];
    
    NSString *lowercaseFirstChar = [[key substringToIndex:1] lowercaseString];
    
    [key replaceCharactersInRange:NSMakeRange(0, 1) withString:lowercaseFirstChar];
    
    if (value) {
        [backingStore setObject:value forKey:key];
    } else {
        [backingStore removeObjectForKey:key];
    }
}
@end
